#ifndef _THREAD_HPP__
#define _THREAD_HPP__

#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>

using namespace std;

namespace ThreadModule
{
    using func_t = function<void(string name)>;
    static int number = 1;  // 线程编号
    // 线程状态
    enum class TheadStatus
    {
        NEW,  // 新建
        RUNNING,  // 启动
        STOP  // 停止
    };

    class Thread
    {
    private:
        static void* Routine(void* args)  // 因为定义为了成员方法，给他传了一个args，实际上有两个参数，还有一个this指针，所以有两种改法，一种是定义在类外，另一个是static，不让她有this指针
        {
            Thread* t = static_cast<Thread*>(args);
            t->_status = TheadStatus::RUNNING;
            t->_func(t->Name());
            return nullptr;
        }

        void EnableDetach()
        {
            _joinable = false;  // 要想让他分离。首先让他可分离
        }
    public:
        Thread(func_t func)
            :_func(func)
            ,_status(TheadStatus::NEW)
            ,_joinable(true)
            {
                _name = "Thread-" + to_string(number++);  // 线程名字编号，每次加一
                _pid = ::getpid();
            }

        ~Thread()
        {}

        bool Start()
        {
            if(_status != TheadStatus::RUNNING)  // 不是启动的才需要启动
            {
                int n = ::pthread_create(&_tid, nullptr, Routine, this);  // 传 this指针，可以访问所有成员变量
                if(n != 0)  // 启动失败
                    return false;
                _status = TheadStatus::RUNNING;
                return true;
            }
            return false;
        }

        bool Stop()
        {
            if(_status == TheadStatus::RUNNING)  // 运行时才能停止
            {
                int n = ::pthread_cancel(_tid);
                if(n != 0) 
                    return false;
                _status = TheadStatus::STOP;
                return true;
            }
            return false;
        }

        bool Join()
        {
            if(_joinable)  // 可以等待
            {
                int n = ::pthread_join(_tid, nullptr);
                if(n != 0)  // 等待失败
                    return false;
                _status = TheadStatus::STOP;
                return true;
            }
            return false;
        }

        void Detach()
        {
            EnableDetach();  // 可分离
            ::pthread_detach(_tid);  // 分离tid
        }

        // 是否可分离了
        bool IsJoinable() 
        {
            return _joinable;
        }

        string Name()
        {
            return _name;
        }
    private:
        string _name;  // 线程名字
        pthread_t _tid;  // 线程地址
        pid_t _pid;  // 进程pid
        bool _joinable;  // 是否是分离的，默认不是，也就是允许join
        func_t _func;  // 线程执行的方法
        TheadStatus _status;  // 线程状态
    };
}

#endif